# -*- coding: utf-8 -*-
"""
Created on Thu May  5 11:09:37 2022

@author: Apple
"""

import os
import sys
from PyQt5.QtWidgets import (QAbstractItemView,QMainWindow,QWidget,QTableWidget,QHBoxLayout,QMessageBox,QApplication,QTableWidgetItem,QHeaderView)
from main_window import Ui_MainWindow
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
import pandas as pd
import numpy as np
import math
import matplotlib.pyplot as plt
import re
from 二分法 import *
from 牛顿二次迭代 import *
from 迭代法 import *

class MainWindow(QMainWindow):
    def __init__(self,parent=None):
        super(MainWindow,self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        
        self.ui.actionopenfile.triggered.connect(self.openfile)
        self.ui.actionversion.triggered.connect(self.showversion)
        self.ui.btn11.clicked.connect(self.savefunc)
        self.ui.btn12.clicked.connect(self.savesettings)
        self.ui.btn13.clicked.connect(self.printresult1)
        self.ui.btn23.clicked.connect(self.printresult2)
        self.ui.btn33.clicked.connect(self.printresult3)
        self.ui.btn15.clicked.connect(self.clearall1)
        self.ui.btn25.clicked.connect(self.clearall2)
        self.ui.btn35.clicked.connect(self.clearall3)
        
        
    # 打开本地文件
    def openfile(self):
        path = os.getcwd() 
        os.startfile(path)
    
    # 展示当前版本
    def showversion(self):
        QMessageBox.about(self, '关于', '当前版本为 V1.0 ')
        
    # 保存函数       
    def savefunc(self):
        
        func = [self.ui.lineEdit11.text()]
        for i in func:
            if i == '':
                QMessageBox.about(self, '警告', '请输入公式')
                return
        print(func)
        path = os.getcwd() + '\\1.csv'
        print(path)
        path = path.replace('\\','/')
        test = pd.DataFrame(data = func)
        test.to_csv(path,index=0)
        QMessageBox.about(self, '完成', '保存成功')
        
    # 保存参数设置        
    def savesettings(self):
        
        settings = []
        settings.append(self.ui.lineEdit12.text())
        settings.append(self.ui.lineEdit13.text())
        settings.append(self.ui.lineEdit14.text())
        for i in range(3):
            data = settings[i]
            if data =='':
                QMessageBox.about(self, '警告', '请输入完整参数')
                return
        print(settings)
        path = os.getcwd() + '\\1.csv'
        print(path)
        path = path.replace('\\','/')
        test = pd.DataFrame(data = settings)
        test.to_csv(path,index=0)
        QMessageBox.about(self, '完成', '保存成功')
    
    def printresult1(self):
        
        with open("scheme2.txt", "r") as f:  # 打开文件
            data = f.read()
        self.ui.textEdit1.setText(data)
        
    def printresult2(self):
        
        with open("scheme1.txt", "r") as f:  # 打开文件
            data = f.read()
        self.ui.textEdit2.setText(data)
    
    def printresult3(self):
        
        with open("scheme3.txt", "r") as f:  # 打开文件
            data = f.read()
        self.ui.textEdit3.setText(data)
        
    def clearall1(self):
        self.ui.textEdit1.clear()
    
    def clearall2(self):
        self.ui.textEdit2.clear()
    
    def clearall3(self):
        self.ui.textEdit3.clear()
    
    def functiongx(self,x):
        gx = math.log(x+2)
        return gx

    def literation(self,x,error):
        gx = functiongx(x)
        K = []
        while abs(gx-x)>=error:
            k = []
            k.append(x)
            k.append(gx)
            K.append(k)
            x = gx
            gx = functiongx(x)
        return K

    def literation_main(self,x0,error):
        
        type = sys.getfilesystemencoding()
        sys.stdout = Logger('scheme1.txt')
        
        x = sp.symbols('x')
        y = x - sp.log(x+2)
        
        print('函数表达式为: f(x) =',y)
        print('初始近似值x0为%.2f'%x0)
        
        K = literation(x0,error)
        # print(K)
        
        df = pd.DataFrame(K,columns=['xk','f(xk)'])
        
        print(f'计算精度为{error}')
        print(f'经过{len(K)}次迭代后，xk的值为{K[-1][1]}，此时f(xk)={K[-1][1] - functiongx(K[-1][1])}')
        print('迭代法求解结果如下：')
        print(df)
    
    def calvalue(self,x): # 函数值计算
        y = x-math.cos(x)
        return y

    def dichotomy(self,a:float,b:float,c:float): # 二分法近似求解根
        x = (a+b)/2
        fx = calvalue(x)
        K = []
        
        while abs(fx)>=c:
            k = []
            k.append(a)
            k.append(b)
            x = (a+b)/2
            k.append(x)
            fx = calvalue(x)
            k.append(fx)
            if fx>0:
                b = x
            elif fx<0:
                a = x
            else:
                K.append(k)
                break

            K.append(k)
        return K

    def dichotomy_main(self,a,b,c):
        
        type = sys.getfilesystemencoding()
        sys.stdout = Logger('scheme2.txt')
        
        x = sp.symbols('x')
        y = x-sp.cos(x)
        
        print('函数表达式为: f(x) =',y)
        print('区间下界为%.2f,区间上界为%.2f'%(a,b))
        K = dichotomy(a,b,c)
        # print(K)
        
        df = pd.DataFrame(K,columns=["ak", 'bk',"xk", "f(xk)"])
        
        print(f'计算精度为{c}')
        print(f'经过{len(K)}次迭代后，xk的值为{K[-1][2]}，此时f(xk)={K[-1][3]}')
        print('二分法求解结果如下：')
        print(df)
    
    def calvalue(self,y,x,x0): # 函数值求解

        fx = float(y.evalf(subs={x:x0}))
        return fx

    def derfunction(self,y,x): # 输出导函数表达式及在x0处的值
        dy = sp.diff(y,x)
        return dy

    def newton(self,y,x,x0,eps,m): # y为函数表达式,x为自变量符号,x0为初始点,eps为精度,m为重根个数 

        fx = calvalue(y,x,x0) # 代入y，求解出x0对应的函数值
        
        y1 = derfunction(y,x) # 求解出导函数表达式
        f1x = calvalue(y1,x,x0) # 代入y1，求解出x0对应的函数值
        
        x1 = x0-m*fx/f1x # 计算xk+1
        
        k = 0
        K = []
        
        while abs(x1-x0)>=eps:# 迭代
            K.append([k,x0,fx])
            k+=1
            x0 = x1
            fx = calvalue(y,x,x0)
            f1x = calvalue(y1,x,x0)
            x1 = x0-m*fx/f1x
            
        K.append([k,x0,fx])
        
        return k,x0,fx,K

    def calMR(self,y,x,x0,a): # 计算重根个数 
        b = 0
        fx = calvalue(y,x,x0)
        # print(fx)
        while(abs(fx)<0.001 and b<a):
            b+=1
            y = derfunction(y,x)
            fx = calvalue(y,x,x0)
        return b
            

    def newton_main(self,):
        
        type = sys.getfilesystemencoding()
        sys.stdout = Logger('scheme3.txt')
        
        x = sp.symbols('x')
        # y = 27*x**3+54*x**2+36*x+8 # 定义函数表达式
        # y = 36*x**4-12*x**3+37*x**2-12*x+1
        y = 2*sp.exp(x-1)-x**2-1
        # y = sp.log(3-x)+x-2
        a = 4
        
        print('函数表达式为: f(x) =',y)
        
        x0 = 0 # 设置初始值
        eps = 0.0000001 # 设置精度
        m = 1
        print(f'计算精度为{eps}')
        
        k,x0,fx,K = newton(y,x,x0,eps,m)

            
        print(f'经过{k}次迭代后，xk的值为{x0}，此时f(xk)={fx}')
        
        b = calMR(y,x,x0,a)
        print('重根个数为:',b)
        
        x0 = 1 # 重置初始值
        print('改进牛顿方法求得结果如下：')
        k,x0,fx,K = newton(y,x,x0,eps,b)
        data = pd.DataFrame(K,columns=["k", "xk", "f(xk)"])
        print(data)
        print('前向误差为：',abs(fx),'后向误差为：',abs(2-x0))
    
        
if __name__=="__main__":
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())